package com.imagine.service.impl;

import com.alibaba.fastjson.JSON;
import com.imagine.common.Global;
import com.imagine.entity.*;
import com.imagine.mapper.DelegationMapper;
import com.imagine.service.*;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

import javax.jms.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by liangyue on 2017/9/26.
 */
@Service
public class DelegationServiceImpl implements DelegationService {
    @Autowired
    DelegationMapper delegationMapper;
    @Autowired
    CapitalAccountService capitalAccountService;
    @Autowired
    DelegationStateService delegationStateService;
    @Autowired
    AccountStockService accountStockService;
    @Autowired
    StockService stockService;

    //获取当前股票的卖家等待队列
    private List<Delegation> sellSideList;

    //获取当前股票的买家等待队列
    private List<Delegation> buySideList;

    @Override
    public Delegation getDelegationById(int delegationId){
        return delegationMapper.getDelegationById(delegationId);

    }
    @Override
    public List getDelegationSubmitted(){
        return delegationMapper.getDelegationSubmitted();

    }

    @Override
    public void initSecurityDealInfo(){

        List<String> idList =  delegationMapper.getSecuIdDelegSubmitted();

        for(String id : idList){
            Deal deal = new Deal();
            List<Delegation> buyDelegationList = delegationMapper.getBuyDelegationListById(id);
            Collections.sort(buyDelegationList, new Comparator<Delegation>() {

                @Override
                public int compare(Delegation o1, Delegation o2) {
                    double i = o2.getDelegationPrice() - o1.getDelegationPrice();
                    if (i > 0){
                        return 1;
                    }
                    else if(i < 0){
                        return -1;
                    }
                    else {
                        return o1.getDelegationTime().compareTo(o2.getDelegationTime());
                    }
                }
            });
            List<Delegation> sellDelegationList = delegationMapper.getSellDelegationListById(id);
            Collections.sort(sellDelegationList, new Comparator<Delegation>() {

                @Override
                public int compare(Delegation o1, Delegation o2) {
                    double i = o1.getDelegationPrice() - o2.getDelegationPrice();
                    if (i > 0){
                        return 1;
                    }
                    else if(i < 0){
                        return -1;
                    }
                    else {
                        return o2.getDelegationTime().compareTo(o1.getDelegationTime());
                    }
                }
            });
            deal.setSecurityId(id);
            deal.setBuySideDelegationList(buyDelegationList);
            deal.setSellSideDelegationList(sellDelegationList);
            Global.securityDealInfo.put(id, deal);

        }
        System.out.println(JSON.toJSONString(Global.securityDealInfo));
    }
    @Override
    public void updateDelegationState(HashMap hashMap){
        delegationMapper.updateDelegationState(hashMap);
    }


    @Override
    public int insertDelegation(Delegation delegation){
        int delegationId = delegationMapper.insertDelegation(delegation);
        Deal deal;

        //如果整个列表为空或者列表中不包含该证券的信息
        if(!Global.securityDealInfo.containsKey(delegation.getSecurityId())){
            deal = new Deal(delegation.getSecurityId());
            if (delegation.getDelegationDirection().equals("证券买入")){
                List<Delegation> buySideList = new ArrayList();
                buySideList.add(delegation);
                deal.setBuySideDelegationList(buySideList);

            }
            else{
                List<Delegation> sellSideList = new ArrayList();
                sellSideList.add(delegation);
                deal.setSellSideDelegationList(sellSideList);
            }


            Global.securityDealInfo.put(delegation.getSecurityId(), deal);
        }
        else{
            deal = Global.securityDealInfo.get(delegation.getSecurityId());
            if (delegation.getDelegationDirection().equals("证券买入")){
                List buySideList;
                if (deal.getBuySideDelegationList().equals(null)){
                    buySideList = new ArrayList();


                }
                else {
                    buySideList = deal.getBuySideDelegationList();
                }
                buySideList.add(delegation);
                deal.setBuySideDelegationList(buySideList);
            }
            else{
                List sellSideList;
                if (deal.getSellSideDelegationList().equals(null)){
                    sellSideList = new ArrayList();


                }
                else {
                    sellSideList = deal.getSellSideDelegationList();
                }
                sellSideList.add(delegation);
                deal.setSellSideDelegationList(sellSideList);
            }


        }
        return delegationId;
    }
    @JmsListener(destination="delegation_apply_queue")
    public HashMap handleDelegation(Delegation newDelegation){
        HashMap resultMap = new HashMap();
        CapitalAccount account;
        //如果新的委托订单的资金账户不存在，则返回相应错误
        if((account = capitalAccountService.getCapitalAccountById(newDelegation.getcAccountId()))==null){
            resultMap.put("code", 1);
            resultMap.put("message", "该资金账户不存在");
            return resultMap;
        }
        //判断买卖的股票是否存在
        if(stockService.queryStock(String.valueOf(newDelegation.getSecurityId())).getCode() != 0){
            resultMap.put("code", 1);
            resultMap.put("message", "该股票不存在");
            return resultMap;
        }

        //获取等待队列
        Deal deal;
        if(!Global.securityDealInfo.containsKey(newDelegation.getSecurityId())){
            deal = new Deal(newDelegation.getSecurityId());
        }

        else {
            deal = Global.securityDealInfo.get(newDelegation.getSecurityId());

        }

        //获取当前股票的卖家等待队列
        sellSideList = deal.getSellSideDelegationList();

        //获取当前股票的买家等待队列
        buySideList = deal.getBuySideDelegationList();
        System.out.println(buySideList);
        if (newDelegation.getDelegationDirection().equals("证券买入")){
            double applyAmount = newDelegation.getDelegationNum()*newDelegation.getDelegationPrice();
            if(account.getRemainAmount() < applyAmount){
                resultMap.put("code", 1);
                resultMap.put("message", "用户资金不足");
                return resultMap;
            }
            for(Delegation delegation : sellSideList){
                if (newDelegation.getcAccountId().equals(delegation.getcAccountId())){
                    resultMap.put("code", 1);
                    resultMap.put("message", "您已经申请卖出该股票，请先撤回再申请买入");
                    return resultMap;
                }
            }
            //用户资金充足，符合条件，将用户的委托订单插入数据库
            insertDelegation(newDelegation);

            //减少用户可用资金
            double amount = newDelegation.getDelegationNum() * newDelegation.getDelegationPrice();
            capitalAccountService.updateRemainOrUsable(1, newDelegation.getcAccountId(), "-", amount);

            //将订单状态记录插入数据库
            DelegationState delegationState = new DelegationState(newDelegation.getDelegationId(), 0, null);
            delegationStateService.insertDelegationState(delegationState);
            for(int i = 0; i < sellSideList.size() && !sellSideList.isEmpty() && newDelegation.getDelegationPrice() >= sellSideList.get(i).getDelegationPrice(); i++){
                if(sellSideList.get(i).getDelegationNum() == newDelegation.getDelegationNum()){
                    //新进入的订单是买家订单而成交
                    makeBargain(newDelegation, i, 0);
                    resultMap.put("code", 1);
                    resultMap.put("message", "委托成功，已成交");
                    return resultMap;
                }
            }
            insertDelegationToDealList(newDelegation, 0);

        }
        if (newDelegation.getDelegationDirection().equals("证券卖出")) {
            //判断用户是否有足够数量的股票
            AccountStock tempAccountStock = new AccountStock(newDelegation.getcAccountId(), newDelegation.getSecurityId());

            if(accountStockService.getAccountStockNumById(tempAccountStock) == null){
                resultMap.put("code", 1);
                resultMap.put("message", "您的仓位内没有该股票");
                return resultMap;
            }
            if((Integer)accountStockService.getAccountStockNumById(tempAccountStock)<newDelegation.getDelegationNum()){
                resultMap.put("code", 1);
                resultMap.put("message", "您的持仓不够卖出该数量的股票");
                return resultMap;
            }
            for(Delegation delegation : buySideList){
                if (newDelegation.getcAccountId().equals(delegation.getcAccountId())){
                    resultMap.put("code", 1);
                    resultMap.put("message", "您已经申请买入该股票，请先撤回再申请卖出");
                    return resultMap;
                }
            }
            //用户资金充足，符合条件，将用户的委托订单插入数据库
            insertDelegation(newDelegation);

            //减少用户可用股票数量
            accountStockService.updateStockOrUsable(1, newDelegation.getcAccountId(), "-", new AccountStock(newDelegation.getcAccountId(), newDelegation.getSecurityId(), newDelegation.getDelegationNum(), newDelegation.getDelegationNum()));

            //将订单状态记录插入数据库
            DelegationState delegationState = new DelegationState(newDelegation.getDelegationId(), 0, null);
            delegationStateService.insertDelegationState(delegationState);
            for(int i = 0; i < buySideList.size() && !buySideList.isEmpty() && newDelegation.getDelegationPrice() <= buySideList.get(i).getDelegationPrice(); i++){
                if(buySideList.get(i).getDelegationNum() == newDelegation.getDelegationNum()){
                    //新进入的订单是卖家订单而成交
                    makeBargain(newDelegation, i, 1);
                    resultMap.put("code", 0);
                    resultMap.put("message", "委托成功，已成交");
                    return resultMap;
                }
            }
            insertDelegationToDealList(newDelegation, 1);
        }

        System.out.println(buySideList);
        System.out.println(sellSideList);
        resultMap.put("code", 0);
        resultMap.put("message", "委托成功，待成交");
        return resultMap;
    }



    //将新订单加入等待成交列表，type是0表示加入等待买入列表，type是1表示加入等待卖出列表
    private void insertDelegationToDealList(Delegation newDelegation, int type){
        Deal deal = Global.securityDealInfo.get(newDelegation.getSecurityId());

        if(type == 1){
            List<Delegation> sellSideList = deal.getSellSideDelegationList();
            for (int i = 0; i < sellSideList.size(); i++){
                if (sellSideList.get(i).getDelegationPrice() < newDelegation.getDelegationPrice()){
                    sellSideList.add(i, newDelegation);
                    return;
                }
            }
            sellSideList.add(newDelegation);
        }
        if(type == 0){
            List<Delegation> buySideList = deal.getBuySideDelegationList();
            for (int i = 0; i < buySideList.size(); i++){
                if (buySideList.get(i).getDelegationPrice() > newDelegation.getDelegationPrice()){
                    buySideList.add(i, newDelegation);
                    return;
                }
            }
            buySideList.add(newDelegation);
        }
    }

    private void makeBargain(Delegation newDelegation, int index, int type){
        double amount = newDelegation.getDelegationNum() * newDelegation.getDelegationPrice();
        Delegation oldDelegation = null;
        double bargainPrice;
        //添加用户的持仓股票
        AccountStock accountStock1 = new AccountStock(
                newDelegation.getcAccountId(),
                newDelegation.getSecurityId(),
                newDelegation.getDelegationNum(),
                newDelegation.getDelegationNum());

        if (type ==0){//newDelegation是买家订单
            oldDelegation = sellSideList.get(index);
            bargainPrice = oldDelegation.getDelegationPrice();
            AccountStock accountStock2 = new AccountStock(
                    oldDelegation.getcAccountId(),
                    newDelegation.getSecurityId(),
                    newDelegation.getDelegationNum(),
                    newDelegation.getDelegationNum());
            //当成交时，买家的持仓增加
            accountStockService.insertAccountStock(accountStock1);
            //当成交时，卖家的持仓减少
            accountStockService.subAccountStock(accountStock2);
            //更新买家可用余额
            if (amount > bargainPrice){
                capitalAccountService.updateRemainOrUsable(1, accountStock1.getcAccountId(), "+", amount - bargainPrice);
            }
            //当成交时买家余额减少
            capitalAccountService.updateRemainOrUsable(0, accountStock1.getcAccountId(), "-", amount);
            //当成交时卖家余额增加
            capitalAccountService.updateRemainOrUsable(0, accountStock2.getcAccountId(), "+", amount);
            sellSideList.remove(index);

        }
        else{//卖家订单
            oldDelegation = buySideList.get(index);
            AccountStock accountStock2 = new AccountStock(
                    oldDelegation.getcAccountId(),
                    newDelegation.getSecurityId(),
                    newDelegation.getDelegationNum(),
                    newDelegation.getDelegationNum());
            bargainPrice = oldDelegation.getDelegationPrice();
            //当成交时，买家的持仓增加
            accountStockService.insertAccountStock(accountStock2);
            //当成交时，卖家的持仓减少
            accountStockService.subAccountStock(accountStock1);
            //更新买家可用余额
            if (amount < bargainPrice){
                capitalAccountService.updateRemainOrUsable(1, accountStock2.getcAccountId(), "+", amount - bargainPrice);
            }
            //当成交时买家余额减少
            capitalAccountService.updateRemainOrUsable(0, accountStock1.getcAccountId(), "+", amount);
            //当成交时卖家余额增加
            capitalAccountService.updateRemainOrUsable(0, accountStock2.getcAccountId(), "-", amount);
            buySideList.remove(index);
        }


        //更改数据库中委托的状态为2
        HashMap map1 = new HashMap<>();
        map1.put("delegationId", newDelegation.getDelegationId());
        map1.put("delegationState", 2);
        map1.put("bargainPrice", bargainPrice);
        map1.put("bargainAmount", bargainPrice * newDelegation.getDelegationNum());
        delegationMapper.makeBargain(map1);

        HashMap map2 = new HashMap<>();
        map2.put("delegationId", oldDelegation.getDelegationId());
        map2.put("delegationState", 2);
        map2.put("bargainPrice", bargainPrice);
        map2.put("bargainAmount", bargainPrice * newDelegation.getDelegationNum());
        delegationMapper.makeBargain(map2);

        //插入订单状态数据库
        DelegationState delegationState1 = new DelegationState(newDelegation.getDelegationId(), 2, null);
        delegationStateService.insertDelegationState(delegationState1);

        DelegationState delegationState2 = new DelegationState(oldDelegation.getDelegationId(), 2, null);
        delegationStateService.insertDelegationState(delegationState2);
    }

    @Override
    public BaseResult backoutDelegation(int delegationId){
        //更改数据库中委托的状态为3，表示订单处于撤回状态
        Delegation delegation = delegationMapper.getDelegationById(delegationId);
        System.out.println(delegation);
        HashMap map = new HashMap<>();
        map.put("delegationId", delegationId);
        map.put("delegationState", 3);
        BaseResult result = new BaseResult();
        delegationMapper.updateDelegationState(map);

        DelegationState state = new DelegationState(delegationId, 3, null);
        delegationStateService.insertDelegationState(state);

        if (delegation.getDelegationDirection().equals("证券买入")){
            //更新买家可用余额
            capitalAccountService.updateRemainOrUsable(1, delegation.getcAccountId(), "+", delegation.getDelegationNum()*delegation.getDelegationPrice());
            //删除列表中的申请
            sellSideList.remove(delegation);
        }
        else {
            AccountStock accountStock = new AccountStock(delegation.getcAccountId(), delegation.getSecurityId(), delegation.getDelegationNum(), delegation.getDelegationNum());
            //更新卖家可用股票余额
            accountStockService.updateStockOrUsable(1, delegation.getcAccountId(), "+", accountStock);
            //删除列表中的申请
            buySideList.remove(delegation);
        }
        return result;
    }

    @Override
    public BaseResult getBargainByCId(String cAccountId){
        BaseResult result = new BaseResult();
        result.success(delegationMapper.getBargainByCId(cAccountId));
        return result;
    }

    @Override
    public BaseResult getDelegationsByCId(String cAccountId){
        BaseResult result = new BaseResult();
        result.success(delegationMapper.getDelegationsByCId(cAccountId));
        return result;
    }

}
